#import "ALTemplateEditorPopoverController.h"
#import <SMRColumnView/SMRColumnEntry.h>
#import "SMRPopoverWindow.h"
#import "NSObject+BlockObservation.h"
#import "NSManagedObjectContext+SMRAdditions.h"
#import "ALEntryTemplate.h"
#import "ALElementTemplate.h"
#import "ALEntry.h"
#import "ALElement.h"


#pragma mark -
@interface ALTemplateEditorPopoverController(ALTemplateEditorPopoverControllerPrivateMethods)
-(void)tilePopoverFrame_;
-(void)tileElementsColumnView_;
-(void)dismissPopover_;
-(void)toggleEditing_;
@end


#pragma mark -
@implementation ALTemplateEditorPopoverController

@synthesize templateEditorObject;
@synthesize elementsColumnView;
@synthesize elementTemplatePrototype;
@synthesize entryDetailsView;
@synthesize descriptionTextField;
//@synthesize textElementDetailsView;


-(void)awakeFromNib {
//	[[self textElementDetailsView] setTag:ALElementDetailsViewBaseTag + ALElementTypeText];
    [[self elementsColumnView] setVerticalPadding:15.0f];
    [[self elementsColumnView] setHorizontalPadding:12.0f];
    [[self elementsColumnView] setDrawsHighlight:NO];
    [[self elementsColumnView] setAnimated:NO];
	[[self elementsColumnView] setChildEntriesSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:ALLineNumberKey ascending:YES]]];
    [[self elementsColumnView] bind:SMRColumnViewContentBinding toObject:self withKeyPath:@"templateEditorObject.elementTemplates" options:nil];
    
    [[self elementTemplatePrototype] setSelectable:YES];
    [[self elementTemplatePrototype] setEditable:YES];
    
    NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
	[noteCenter addObserver:self selector:@selector(elementsColumnViewFrameDidChange:) name:NSViewFrameDidChangeNotification object:[self elementsColumnView]];
	AMBlockTask firstResponderTask = ^(id object, NSDictionary *change) {
		NSResponder *currentResponder = [[self window] firstResponder];
		NSResponder *previousResponder = [change valueForKey:NSKeyValueChangeOldKey];
		BOOL currentResponderIsColumnViewDescendent = [currentResponder isKindOfClass:[NSView class]] && [(NSView *)currentResponder isDescendantOf:[self elementsColumnView]];

		// Transferring firstResponder from the field editor temporarily moves firstResponder to the window (via NSWindow's endEditingFor:), but will continue to the next key view immediately after - ignore this change
		if (currentResponder == [self window] && [previousResponder isKindOfClass:[NSText class]] && [(NSText *)previousResponder isFieldEditor])
			return;
		if (!currentResponderIsColumnViewDescendent) {
			[[self elementsColumnView] deselectAllEntries];
			return;
		}
		if (currentResponderIsColumnViewDescendent && [[[self elementsColumnView] selectedEntries] count] == 0) {
			NSArray *entries = [[self elementsColumnView] childEntries];
			[[self elementsColumnView] selectEntry:[entries objectAtIndex:0] extendSelection:NO];
		}
	};
	[[self window] addObserverForKeyPath:@"firstResponder" options:NSKeyValueObservingOptionOld task:firstResponderTask];
}

-(void)displayPopoverForObject:(id)templateObject inView:(NSView *)targetView withRect:(NSRect)targetRect {
	[self setTemplateEditorObject:templateObject];
	[[self elementsColumnView] layoutWithAnimation:NO];
	[[self window] makeFirstResponder:[self descriptionTextField]];
	[self tilePopoverFrame_];
	[self tileElementsColumnView_];
	[(SMRPopoverWindow *)[self window] presentPopoverFromRect:targetRect inView:targetView permittedArrowDirections:SMRPopoverArrowDirectionAny animated:YES];
}


#pragma mark -
#pragma mark Notifications

-(void)elementsColumnViewFrameDidChange:(NSNotification *)note {
//	NSLog(@"%@", NSStringFromRect([[self elementsColumnView] frame]));
	[self tilePopoverFrame_];
}


#pragma mark -
#pragma mark Actions

-(IBAction)addElementTemplate:(id)sender {
	ALEntryTemplate *entryTemplate = [self templateEditorObject];
	if (!entryTemplate)
		return;
	NSUndoManager *undoManager = [[self window] undoManager];
	[undoManager beginUndoGrouping];
	[undoManager setActionName:@"Insert Element"];

	ALElementTemplate *elementTemplate = [ALElementTemplate insertInManagedObjectContext:[self managedObjectContext]];
	
	NSUInteger lineNumber = [[entryTemplate elementTemplates] count];
	if ([sender isKindOfClass:[NSView class]]) {
		SMRColumnEntry *clickedEntry = [[self elementsColumnView] entryWithView:sender];
		NSArray *entries = [[self elementsColumnView] childEntries];
		NSUInteger entryIndex = [entries indexOfObject:clickedEntry];
		if (entryIndex != NSNotFound)
			lineNumber = entryIndex + 1;
	}
	[elementTemplate setLineNumber:[NSNumber numberWithUnsignedInteger:lineNumber]];
	for (ALElementTemplate *template in [entryTemplate elementTemplates]) {
		NSUInteger currentLineNumber = [[template lineNumber] unsignedIntegerValue];
		if (currentLineNumber >= lineNumber)
			[template setLineNumber:[NSNumber numberWithUnsignedInteger:(currentLineNumber + 1)]];
	}
	[elementTemplate setEntryTemplate:entryTemplate];
	for (ALEntry *entry in [entryTemplate entries]) {
		ALElement *element = [elementTemplate stamp];
		[element setEntry:entry];
	}
	[undoManager endUndoGrouping];
}


#pragma mark -
#pragma mark Window delegate

-(NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
    return [[self managedObjectContext] undoManager];
}


#pragma mark -
#pragma mark Column view delegate

-(NSView *)columnView:(SMRColumnView *)aColumnView willForwardHitTestAtPoint:(NSPoint)aPoint toSubview:(NSView *)subview {
	NSView *editingView = [[aColumnView editingEntry] view];
	if (editingView && [subview isDescendantOf:editingView])
		return subview;
	if ([subview isKindOfClass:[NSButton class]])
		return subview;
	return aColumnView;
}

-(BOOL)columnView:(SMRColumnView *)aColumnView doCommandBySelector:(SEL)aSelector {
	if (aSelector == @selector(cancelOperation:)) {
//		[[[self window] parentWindow] makeKeyWindow];
		[self dismissPopover_];
		return YES;
	}
	if (aSelector == @selector(insertNewline:)) {
		[self toggleEditing_];
		return YES;
	}
	if (aSelector != @selector(deleteBackward:)) 
		return NO;
	
	if ([[[self elementsColumnView] childEntries] count] < 2) {
		NSBeep();
		return YES;
	}
	NSArray *selectedTemplates = [[self elementsColumnView] selectedObjects];
	[[self managedObjectContext] smrDeleteObjects:selectedTemplates];
	return YES;
}


#pragma mark -
#pragma mark Event handling

-(void)keyDown:(NSEvent *)theEvent {
	[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
}

-(void)cancelOperation:(id)sender {
	[self dismissPopover_];
}

-(void)insertNewline:(id)sender {
	[self toggleEditing_];
}

-(void)dismissPopover_ {
	[[[self window] parentWindow] makeKeyWindow];
}

-(void)toggleEditing_ {
	NSArray *selectedEntries = [[self elementsColumnView] selectedEntries];
	if ([selectedEntries count] != 1) 
		NSBeep();
	else if ([[self elementsColumnView] editingEntry])
		[[self elementsColumnView] stopEditing];
	else 
		[[self elementsColumnView] editEntry:[selectedEntries objectAtIndex:0] atPoint:NSZeroPoint];
}


#pragma mark -
#pragma mark Private methods

-(void)tilePopoverFrame_ {
	NSRect columnViewRect = [[self elementsColumnView] frame];
	NSRect entryDetailsRect = [[self entryDetailsView] frame];
	entryDetailsRect.origin.y = columnViewRect.size.height;
	[[self entryDetailsView] setFrame:entryDetailsRect];
	
	NSSize popoverContentSize = columnViewRect.size;
	popoverContentSize.height += entryDetailsRect.size.height;
	[(SMRPopoverWindow *)[self window] setPreferredContentSize:popoverContentSize];
}

-(void)tileElementsColumnView_ {
	NSRect elementsColumnViewFrame = [[self elementsColumnView] frame];
	elementsColumnViewFrame.origin.y = 0;
    NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
	[noteCenter removeObserver:self name:NSViewFrameDidChangeNotification object:[self elementsColumnView]];
	[[self elementsColumnView] setFrame:elementsColumnViewFrame];
	[noteCenter addObserver:self selector:@selector(elementsColumnViewFrameDidChange:) name:NSViewFrameDidChangeNotification object:[self elementsColumnView]];
}

@end
